// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.operationsdesk.vehicles;

import com.google.inject.Inject;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.opentcs.drivers.vehicle.VehicleCommAdapterMessage;
import org.opentcs.util.gui.BoundsPopupMenuListener;

/**
 * A panel for editing a {@link VehicleCommAdapterMessage} parameter (i.e. a key-value pair).
 */
public class ParameterEditorPanel
    extends
      JPanel {

  private final JTextField keyTextField;
  private final JTextField valueTextField;
  private final Map<String, Set<String>> parameterSuggestions = new HashMap<>();

  /**
   * Creates new instance.
   */
  @Inject
  @SuppressWarnings("this-escape")
  public ParameterEditorPanel() {
    initComponents();
    valueComboBox.addPopupMenuListener(new BoundsPopupMenuListener());
    keyComboBox.addPopupMenuListener(new BoundsPopupMenuListener());
    keyTextField = (JTextField) (keyComboBox.getEditor().getEditorComponent());
    valueTextField = (JTextField) (valueComboBox.getEditor().getEditorComponent());
  }

  /**
   * Sets the parameter suggestions to be used for the key and value suggestions.
   *
   * @param parameterSuggestions The parameter suggestions.
   */
  public void setParameterSuggestions(Map<String, Set<String>> parameterSuggestions) {
    this.parameterSuggestions.putAll(parameterSuggestions);
    keyComboBox.setModel(
        new DefaultComboBoxModel<>(
            parameterSuggestions.keySet().stream()
                .sorted()
                .toArray(String[]::new)
        )
    );
    populateValueSuggestions();
  }

  /**
   * Sets the inputs of this panel according to the given parameter's key and value.
   *
   * @param parameter The parameter.
   */
  public void setParameter(CommAdapterMessageParameter parameter) {
    keyTextField.setText(parameter.key());
    valueTextField.setText(parameter.value());
  }

  /**
   * Returns the parameter as configured via the inputs of this panel.
   *
   * @return The configured parameter.
   */
  public CommAdapterMessageParameter getParameter() {
    return new CommAdapterMessageParameter(keyTextField.getText(), valueTextField.getText());
  }

  private void populateValueSuggestions() {
    Set<String> valueSuggestions = parameterSuggestions.getOrDefault(
        String.valueOf(keyComboBox.getSelectedItem()),
        Set.of()
    );

    Optional<Object> previousContent = Optional.ofNullable(valueComboBox.getEditor().getItem());
    valueComboBox.setModel(
        new DefaultComboBoxModel<>(
            valueSuggestions.stream()
                .sorted()
                .toArray(String[]::new)
        )
    );
    // Setting the combo box model resets the combo box's selection and the content of its text
    // field. Therefore, restore the previous content.
    previousContent.ifPresent(s -> valueComboBox.getEditor().setItem(s));
  }

  // FORMATTER:OFF
  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    keyLabel = new javax.swing.JLabel();
    valueLabel = new javax.swing.JLabel();
    keyComboBox = new javax.swing.JComboBox<>();
    valueComboBox = new javax.swing.JComboBox<>();

    setLayout(new java.awt.GridBagLayout());

    keyLabel.setFont(keyLabel.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/operating/dialogs/sendVehicleCommAdapterMessage"); // NOI18N
    keyLabel.setText(bundle.getString("parameterEditorPanel.label_key.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 3, 0);
    add(keyLabel, gridBagConstraints);

    valueLabel.setFont(valueLabel.getFont());
    valueLabel.setText(bundle.getString("parameterEditorPanel.label_value.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    add(valueLabel, gridBagConstraints);

    keyComboBox.setEditable(true);
    keyComboBox.setPrototypeDisplayValue("tenletters");
    keyComboBox.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        selectedKeyChanged(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 3, 3);
    add(keyComboBox, gridBagConstraints);

    valueComboBox.setEditable(true);
    valueComboBox.setPrototypeDisplayValue("tenletters");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
    add(valueComboBox, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents

  private void selectedKeyChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_selectedKeyChanged
     populateValueSuggestions();
  }//GEN-LAST:event_selectedKeyChanged
  // CHECKSTYLE:ON
  // FORMATTER:ON

  // FORMATTER:OFF
  // CHECKSTYLE:OFF
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JComboBox<String> keyComboBox;
  private javax.swing.JLabel keyLabel;
  private javax.swing.JComboBox<String> valueComboBox;
  private javax.swing.JLabel valueLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
  // FORMATTER:ON
}
